/**
* cJSON 工具包
*/

#pragma once

#include "cJSON.h"
#include "std_err.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* 获取 JSON 字符串表示的 JSON 对象中指定字段的值
* @param json cJSON 对象指针
* @param field 字段名
* @param default_value 默认值。如果无此字段，或出错，则返回默认值。
* @param value [out] 字段的值
*/
double  cjson_get_field_double(cJSON *json, const char *field, double  default_value);
#define cjson_get_field_float( json, field, default_value)  ((float   )round(cjson_get_field_double(json, field, default_value)))
#define cjson_get_field_int64( json, field, default_value)  ((int64_t )round(cjson_get_field_double(json, field, default_value)))
#define cjson_get_field_int32( json, field, default_value)  ((int32_t )round(cjson_get_field_double(json, field, default_value)))
#define cjson_get_field_int16( json, field, default_value)  ((int16_t )round(cjson_get_field_double(json, field, default_value)))
#define cjson_get_field_int8(  json, field, default_value)  ((int8_t  )round(cjson_get_field_double(json, field, default_value)))
#define cjson_get_field_uint64(json, field, default_value)  ((uint64_t)round(cjson_get_field_double(json, field, default_value)))
#define cjson_get_field_uint32(json, field, default_value)  ((uint32_t)round(cjson_get_field_double(json, field, default_value)))
#define cjson_get_field_uint16(json, field, default_value)  ((uint16_t)round(cjson_get_field_double(json, field, default_value)))
#define cjson_get_field_uint8( json, field, default_value)  ((uint8_t )round(cjson_get_field_double(json, field, default_value)))

/**
 * 把 cJSON 数组对象填充到一个数值数组
 * @param arr 必须要是一个 cJSON 数组对象指针。
 * @param values 获取的数据填充到这个数组中。如果为 NULL 则表示新建一个数组。
 * @param count [in/out] 输入时表示 values 中最多可存放的数据个数；输出时表示实际填充的数据个数。values 不为 NULL 时，count 不可为 NULL ；values 为 NULL 时，count 仅用作输出，可为 NULL。
 * @param terminate_value 仅在 values 为 NULL 时有效，表示最后一个数据之后会多填充一个 terminate_value 表示数组结束。
 * @return 如果遇到错误，则返回 NULL。如果 values 有效，则返回 values；如果 values 为 NULL，则返回的是新创建的数组(分配的空间大小是 count + 1 个数据，最后一个是 terminate_value)，用户应在不使用它时调用 free() 释放它 !!!
 */
double * cjson_get_double_array(cJSON *arr, double  *values, size_t *count, double  terminate_value);
float  * cjson_get_float_array (cJSON *arr, float   *values, size_t *count, float   terminate_value);
int64_t* cjson_get_int64_array (cJSON *arr, int64_t *values, size_t *count, int64_t terminate_value);
int32_t* cjson_get_int32_array (cJSON *arr, int32_t *values, size_t *count, int32_t terminate_value);
int16_t* cjson_get_int16_array (cJSON *arr, int16_t *values, size_t *count, int16_t terminate_value);
int8_t * cjson_get_int8_array  (cJSON *arr, int8_t  *values, size_t *count, int8_t  terminate_value);
#define  cjson_get_uint64_array(arr, values, count, terminate_value)  (uint64_t*)cjson_get_int64_array(arr, (int64_t*)values, count, (uint64_t)terminate_value)
#define  cjson_get_uint32_array(arr, values, count, terminate_value)  (uint32_t*)cjson_get_int32_array(arr, (int32_t*)values, count, (uint32_t)terminate_value)
#define  cjson_get_uint16_array(arr, values, count, terminate_value)  (uint16_t*)cjson_get_int16_array(arr, (int16_t*)values, count, (uint16_t)terminate_value)
#define  cjson_get_uint8_array( arr, values, count, terminate_value)  (uint8_t *)cjson_get_int8_array (arr, (int8_t *)values, count, (uint8_t )terminate_value)

/**
 * 获取 JSON 字符串表示的 JSON 对象中指定字符串型字段的值（去掉了前后引号）
 * @param json cJSON 对象指针
 * @param field 字段名
 * @return 正常返回字段的字符串的形式值（去掉了前后引号），如 "{\"name\":\"abc\"}" 会返回 "abc"。失败返回 NULL。
 * @attention 返回的字符串值是通过 malloc() 分配的内存空间，不再使用时需要使用 free() 释放。
*/
const char* cjson_get_field_string(cJSON *json, const char* field);

/**
 * 获取 JSON 字符串表示的 JSON 对象中指定字符串型字段的值（去掉了前后引号），填充到指定的字符串缓冲区
 * @param json cJSON 对象指针
 * @param field 字段名
 * @param strbuf 字符串缓冲区
 * @param bufsize 字符串缓冲区大小。如果缓冲区放不下这个字符串，则只放能放下的部分(长度为 bufsize-1，最后一个字符放 '\0')，并返回 STD_ERR_BUFFER_OVERFLOW。
 * @return 标准错误码。
*/
std_err_t cjson_fill_field_string(cJSON *json, const char* field, char *strbuf, size_t bufsize);

/**
 * 把 cJSON 数组对象变成一个字符串列表（最后一个字符串为 NULL）
 * @param arr 必须要是一个 cJSON 数组对象指针，并且不允许有空字符串（遇到空字符串就表示结束）。
 * @param count 如果不为 NULL，则返回提取的有效字符串数量(不包括最后一个 NULL)。
 * @return 字符串列表。最后一个字符串为 NULL。
 * @attention 返回的字符串列表不再使用时需要使用 FREESTRARR() 释放。
 */
const char** cjson_get_string_array(cJSON *arr, size_t *count/*out*/);

#ifdef __cplusplus
} // extern "C"
#endif
